﻿//Description:接收数据中心任务处理程序入口类
//Copyright (c) : 通力凯顿（北京）系统集成有限公司
//Writer:Wangjh
//create Date:2024-11-11
//Rewriter:
//Rewrite Date:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BusinessRule.Common;
using Newtonsoft.Json;
using log4net;
using System.Configuration;
using System.Data;
using DatabaseAccess.DBUtility;
using System.Net;
using System.IO;
using SendIndustrialNetwork.Service;

namespace SendIndustrialNetwork.ReceiveBusiness
{
    public class ReceiveSaveBusiness
    {
        private static RedisHelper redis = new RedisHelper();
        private const String dcKey = "dcReceive";
        private ILog rsLog = LogHelp.receiveSave; //接收处理程序专用日志 add:wangjh 20241111
        public string dataCenterHost = ConfigurationManager.AppSettings["dataCenterHost"].ToString();//数据中心地址
        public string ToAppID_WMS = ConfigurationManager.AppSettings["ToAppID_WMS"].ToString();//推送目的ID（WMS）
        public string ToAppID_FIVE = ConfigurationManager.AppSettings["ToAppID_FIVE"].ToString();//推送目的ID（五厂）
        /// <summary>
        /// 入口
        /// </summary>
        public void Excute()
        {
            String receiveJson = null;
            do
            {
                //从右取出接收的任务json
                receiveJson = redis.PopListRight(dcKey).ToString();
                if (receiveJson == null)
                    return;
                rsLog.Info("开始处理：" + receiveJson);
                Dictionary<String, String> receivePara = JsonConvert.DeserializeObject<Dictionary<String, String>>(receiveJson);
                //下载文件,具体的解析逻辑，从lymesApi移植

                string DType = receivePara["DType"];//10: 表结构, 20: 表数据, 30: 文件
                string BusinessID = receivePara["BusinessID"].ToString();
                string fileUrl = string.Format("http://{0}:8080/lygkdc-service/lygk/dc/static/{1}", dataCenterHost, BusinessID);
                fileUrl = string.Format("http://localhost/mesreport/files/{0}.json", BusinessID);

                if (DType == "20")
                {
                    string resJson = HttpUtils.Get(fileUrl);
                    rsLog.Info(string.Format("【businessid：{0}】获取的结果：{1}", BusinessID, resJson));
                    Dictionary<String, Object> dicResult = JsonConvert.DeserializeObject<Dictionary<String, Object>>(resJson);
                    if (dicResult.ContainsKey("iszip") && dicResult["iszip"].ToString() == "1")
                    {
                        string decodeZipData = EncryptHelper.DecompressString(dicResult["zipdata"].ToString());//将压缩内容解压，获取要同步的表数据
                        rsLog.Info(string.Format("【businessid：{0}】解压后的结果：{1}", BusinessID, decodeZipData));
                        /**
                         * 解压后的字符串格式为：[{"PROSTATUS": "U","字段1": "XX","字段2": "XX"},{"PROSTATUS": "A","字段1": "XX","字段2": "XX"}]
                         * PROSTATUS字段一定存在
                         * PROSTATUS字段的值有A、U、D三种
                         */
                        dicResult["items"] = JsonConvert.DeserializeObject<List<Dictionary<string, string>>>(decodeZipData);
                    }
                    else
                    {
                        dicResult["items"] = JsonConvert.DeserializeObject<List<Dictionary<string, string>>>(dicResult["items"].ToString());
                    }
                    //同步表数据
                    DealDataTableSync(dicResult);
                }
                else if (DType == "30")
                {
                    string FromAppID = receivePara["FromAppID"];
                    string BsType = receivePara["BsType"];

                    //存为文件
                    string saveFilePath = ConfigurationManager.AppSettings["saveFilePath"].ToString();
                    string resJson = HttpUtils.Get(fileUrl);
                    String filePath = "";
                    if (FromAppID == ToAppID_WMS)
                    {
                        filePath = string.Format("{0}/{1}-{2}-{3}.json", saveFilePath, "WMS", BsType, BusinessID);
                    }
                    else if (FromAppID == ToAppID_FIVE)
                    {
                        filePath = string.Format("{0}/{1}-{2}.json", saveFilePath, BsType, BusinessID);
                    }
                    else
                    {
                        filePath = string.Format("{0}/{1}.json", saveFilePath, BusinessID);
                    }
                    File.WriteAllText(filePath, resJson);
                }
            }
            while (receiveJson != null);

        }

        /// <summary>
        /// 同步表数据方法 add by zhangrj 20240822
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public string DealDataTableSync(Dictionary<string, Object> dicResult)
        {
            /*--------------------------------
             * 局部变量定义
             --------------------------------*/
            string resMsg = string.Empty;//处理消息
            string tableName = dicResult["tablename"].ToString();//表名
            /*--------------------------------
             * 工控网来源数据，部分数据需要特殊处理
             --------------------------------*/
            if (dicResult["fromappid"].ToString() == "lyiot.rbmes")
            {
                RbContainerService rbContainer = new RbContainerService(dicResult);
                rbContainer.Excute();//热表批次除了更新数据，还要单独处理其他逻辑，比如：入库
            }
            /*--------------------------------
             * 开始同步表数据
             * 查询表结构的（列名，列类型，列长度以及是否可为空）
             --------------------------------*/
            string sql = string.Format("SELECT t.TABLE_NAME,t.COLUMN_NAME,t.DATA_TYPE,t.DATA_LENGTH,t.NULLABLE FROM User_Tab_Columns t WHERE t.TABLE_NAME = '{0}'", tableName.ToUpper());
            DataTable dtTb = DatabaseHelper.Query_ReturnDatTable(sql);

            if (dtTb == null || dtTb.Rows.Count == 0)
            {
                resMsg = string.Format("【表名：{0}】未在系统中找到！", tableName);
                rsLog.Info(resMsg);
                return resMsg;
            }
            /*--------------------------------
             * 检查表ID是否存在
             --------------------------------*/
            string tbID = string.Empty;
            if (tableName.ToLower() == "containercurrentinfo")
            {
                tbID = "containerid".ToUpper();//批次汇总表特殊处理，表名ID较为特殊
            }
            else
            {
                tbID = string.Format("{0}ID", dtTb.Rows[0]["TABLE_NAME"].ToString().TrimEnd('2'));//获取表的主键名（可能有带2的表，但ID是不带2，比如：表containerstepworkreport2，其主键为containerstepworkreportid）
            }
            DataRow drID = dtTb.Select(string.Format("COLUMN_NAME = '{0}'", tbID)).FirstOrDefault();//获取主键列的数据类型
            if (drID == null)
            {
                drID = dtTb.Select("COLUMN_NAME = 'ID'").FirstOrDefault();
                if (drID == null)
                {
                    resMsg = string.Format("【表名：{0}】未找到表的ID列名【{1}】或【ID】！", tableName, tbID);
                    rsLog.Info(resMsg);
                    return resMsg;
                }
            }
            /*--------------------------------
             * 循环处理表数据
             --------------------------------*/
            rsLog.Info(string.Format("【表名：{0}】开始处理数据", tableName));
            resMsg = string.Format("【表名：{0}】", tableName);
            List<ExcuteEntity> exList = new List<ExcuteEntity>();
            List<Dictionary<string, string>> items = (List<Dictionary<string, string>>)dicResult["items"];
            for (int i = 0; i < items.Count; i++)
            {
                Dictionary<string, string> row = items[i];
                string idValue = row[drID["COLUMN_NAME"].ToString()];//表ID值
                switch (row["PROSTATUS"].ToUpper())
                {
                    case "A"://插入数据
                        //row.Remove("ID"); //移除表ID，防止与表列名冲突（插入不需要ID数据）
                        //row.Remove(tbID);//同上
                        row.Remove("PROSTATUS");//移除处理类型，防止与表列名冲突
                        sql = string.Format("SELECT 1 FROM {0} t WHERE t.{1} = '{2}'", tableName, drID["COLUMN_NAME"].ToString(), idValue);
                        if (DatabaseHelper.GetSingle(sql) != null) //如果添加的数据存在，则更新
                        {
                            exList.Add(GetUpdateTableDataEntity(row, dtTb, drID));
                            break;
                        }
                        exList.Add(GetInsertTableDataEntity(row, dtTb, drID));
                        break;
                    case "U"://更新数据
                        row.Remove("PROSTATUS");//移除处理类型，防止与表列名冲突
                        sql = string.Format("SELECT 1 FROM {0} t WHERE t.{1} = '{2}'", tableName, drID["COLUMN_NAME"].ToString(), idValue);
                        if (DatabaseHelper.GetSingle(sql) == null) //如果更新的数据不存在，则添加
                        {
                            //row.Remove("ID"); //移除表ID，防止与表列名冲突（插入不需要ID数据）
                            //row.Remove(tbID);//同上
                            exList.Add(GetInsertTableDataEntity(row, dtTb, drID));
                            break;
                        }
                        exList.Add(GetUpdateTableDataEntity(row, dtTb, drID));
                        break;
                    case "D"://删除数据
                        exList.Add(GetDeleTableDataEntity(row, dtTb, drID));
                        break;
                    default:
                        resMsg = string.Format("中第{0}行数据【PROSTATUS】:{1}，定义不明。", i + 1, row["PROSTATUS"]);
                        break;
                }
            }
            DatabaseHelper.ExecuteDataByEntitys(exList);
            /*--------------------------------
             * 处理结束，返回消息
             --------------------------------*/
            resMsg += "，数据处理完成！";
            rsLog.Info(resMsg);
            return resMsg;
        }

        /// <summary>
        /// 获取插入表数据实体（不能插入camstar标准对象）
        /// </summary>
        /// <param name="row"></param>
        /// <param name="dtTb"></param>
        /// <param name="drID"></param>
        /// <returns></returns>
        private ExcuteEntity GetInsertTableDataEntity(Dictionary<string, string> row, DataTable dtTb, DataRow drID)
        {
            ExcuteEntity entity = new ExcuteEntity();
            entity.TableName = dtTb.Rows[0]["TABLE_NAME"].ToString();
            entity.ExcuteType = ExcuteEntity.ExcuteTypeEnum.insert;
            List<FieldEntity> fieldList = new List<FieldEntity>();
            foreach (string key in row.Keys)
            {
                DataRow drTbRow = dtTb.Select(string.Format("COLUMN_NAME = '{0}'", key.ToUpper())).FirstOrDefault();
                if (drTbRow == null)
                {
                    rsLog.Info(string.Format("添加数据时，表未找到列名：{0}的字段，跳过插入", key));
                    continue;
                }
                fieldList.Add(GetFieldEntity(key, row[key], drTbRow["DATA_TYPE"].ToString()));//添加该字段
            }
            //fieldList.Add(GetFieldEntity(drID["COLUMN_NAME"].ToString(), Guid.NewGuid().ToString(), drID["DATA_TYPE"].ToString()));//添加主键（不能插入camstar标准对象）
            entity.ExcuteFileds = fieldList;
            return entity;
        }

        /// <summary>
        /// 获取更新表数据实体
        /// </summary>
        /// <param name="row"></param>
        /// <param name="dtTb"></param>
        /// <param name="drID"></param>
        /// <returns></returns>
        private ExcuteEntity GetUpdateTableDataEntity(Dictionary<string, string> row, DataTable dtTb, DataRow drID)
        {
            string idValue = row[drID["COLUMN_NAME"].ToString()];//表ID值
            ExcuteEntity entity = new ExcuteEntity();
            entity.TableName = dtTb.Rows[0]["TABLE_NAME"].ToString();
            entity.ExcuteType = ExcuteEntity.ExcuteTypeEnum.update;
            List<FieldEntity> fieldList = new List<FieldEntity>();
            row.Remove("ID");
            row.Remove(drID["COLUMN_NAME"].ToString());
            foreach (string key in row.Keys)
            {
                DataRow drTbRow = dtTb.Select(string.Format("COLUMN_NAME = '{0}'", key.ToUpper())).FirstOrDefault();
                if (drTbRow == null)
                {
                    rsLog.Info(string.Format("更新数据时，表未找到列名：{0}的字段，跳过更新", key));
                    continue;
                }
                fieldList.Add(GetFieldEntity(key, row[key], drTbRow["DATA_TYPE"].ToString()));//添加该字段
            }
            entity.ExcuteFileds = fieldList;
            entity.WhereFileds = new List<FieldEntity>() { GetFieldEntity(drID["COLUMN_NAME"].ToString(), idValue, drID["DATA_TYPE"].ToString()) };
            return entity;
        }

        /// <summary>
        /// 获取删除表数据实体
        /// </summary>
        /// <param name="row"></param>
        /// <param name="dtTb"></param>
        /// <param name="drID"></param>
        /// <returns></returns>
        private ExcuteEntity GetDeleTableDataEntity(Dictionary<string, string> row, DataTable dtTb, DataRow drID)
        {
            ExcuteEntity entity = new ExcuteEntity();
            DataRow drIsUse = dtTb.Select(string.Format("COLUMN_NAME = 'ISUSE'")).FirstOrDefault();
            entity.TableName = dtTb.Rows[0]["TABLE_NAME"].ToString();
            if (drIsUse == null)
            {
                entity.ExcuteType = ExcuteEntity.ExcuteTypeEnum.del;
                entity.WhereFileds = new List<FieldEntity>() { GetFieldEntity(drID["COLUMN_NAME"].ToString(), row[drID["COLUMN_NAME"].ToString()], drID["DATA_TYPE"].ToString()) };
                //rsLog.Info(string.Format("表没有isuse字段，无法删除"));
                return entity;
            }
            /*如果存在isuse字段，则更新该字段为1，表示删除*/
            entity.ExcuteType = ExcuteEntity.ExcuteTypeEnum.update;
            entity.ExcuteFileds = new List<FieldEntity>() { GetFieldEntity("ISUSE", "1", drIsUse["DATA_TYPE"].ToString()) };
            entity.WhereFileds = new List<FieldEntity>() { GetFieldEntity(drID["COLUMN_NAME"].ToString(), row[drID["COLUMN_NAME"].ToString()], drID["DATA_TYPE"].ToString()) };
            return entity;
        }

        private FieldEntity GetFieldEntity(string colName, string colValue, string dataType)
        {
            switch (dataType)
            {
                case "DATE":
                    if (string.IsNullOrWhiteSpace(colValue) || colValue.ToLower() == "null")
                    {
                        return new FieldEntity(colName, null, FieldEntity.FieldTypeEnum.DateTime);
                    }
                    return new FieldEntity(colName, colValue, FieldEntity.FieldTypeEnum.DateTime);
                case "NUMBER":
                    if (string.IsNullOrWhiteSpace(colValue) || colValue.ToLower() == "null")
                    {
                        return new FieldEntity(colName, null, FieldEntity.FieldTypeEnum.Numer);
                    }
                    if (colName.ToUpper() == "ISUSE") //isuse字段要单独处理
                    {
                        int isuse = 0;
                        if (int.TryParse(colValue.Trim(), out isuse))
                        {
                            return new FieldEntity(colName, isuse, FieldEntity.FieldTypeEnum.Numer);
                        }
                        return new FieldEntity(colName, colValue.Trim().ToLower() == "true" ? 1 : 0, FieldEntity.FieldTypeEnum.Numer);
                    }
                    if (colValue.Contains(".")) //如果包含有小数，则需要转换
                    {
                        return new FieldEntity(colName, double.Parse(colValue), FieldEntity.FieldTypeEnum.Numer);
                    }
                    return new FieldEntity(colName, colValue, FieldEntity.FieldTypeEnum.Numer);
                case "CLOB":
                    return new FieldEntity(colName, colValue, FieldEntity.FieldTypeEnum.Clob);
                default:
                    return new FieldEntity(colName, colValue, FieldEntity.FieldTypeEnum.Str);
            }
        }
    }
}
